package com.example.myapplication.widgets.calendar.statistics;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.example.myapplication.R;
import com.example.myapplication.utils.CollectionUtils;
import com.example.myapplication.utils.TimeUtils;

import java.util.List;
import java.util.Locale;

public class StatisticsCalendarView extends View {

    private int mWidth, mHeight;

    // region attr设置属性
    private Drawable mCorrectDrawable;
    private Drawable mErrorDrawable;
    private Drawable mNormalDrawable;

    private int mNumberTextSize = 36;
    private int mItemSize = 60;
    private int mNumberTextColor = Color.GRAY;
    // endregion

    private float mItemPadding, mVerticalSpace;

    // 是否展示日期数字
    private boolean isShowNumber = true;
    // 是否展示周状态
    private boolean isWeek;

    // 第一天的日期年月日
    private int mYear, mMonth, mDay;
    private int mLastDay, mFirstDayWeek;

    private List<StatisticsBean> mStatisticsBeanList;

    private Paint mPaint;

    public StatisticsCalendarView(Context context) {
        super(context);
        init(context, null);
    }

    public StatisticsCalendarView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public StatisticsCalendarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    public StatisticsCalendarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    private void init(Context context, @Nullable AttributeSet attrs) {
        if (attrs != null) {
            TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.StatisticsCalendarView);
            mCorrectDrawable = typedArray.getDrawable(R.styleable.StatisticsCalendarView_scv_correct_drawable);
            mErrorDrawable = typedArray.getDrawable(R.styleable.StatisticsCalendarView_scv_error_drawable);
            mNormalDrawable = typedArray.getDrawable(R.styleable.StatisticsCalendarView_scv_normal_drawable);

            mNumberTextSize = typedArray.getDimensionPixelSize(R.styleable.StatisticsCalendarView_scv_number_text_size, mNumberTextSize);
            mItemSize = typedArray.getDimensionPixelSize(R.styleable.StatisticsCalendarView_scv_item_size, mItemSize);

            mNumberTextColor = typedArray.getColor(R.styleable.StatisticsCalendarView_scv_number_text_color, mNumberTextColor);

            isShowNumber = typedArray.getBoolean(R.styleable.StatisticsCalendarView_scv_is_show_number, isShowNumber);
            typedArray.recycle();
        }

        mPaint = new Paint();
        mPaint.setTextSize(mNumberTextSize);
        mPaint.setColor(mNumberTextColor);
        mPaint.setAntiAlias(true);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        mWidth = getWidth();
        mHeight = getHeight();

        mItemPadding = (mWidth - mItemSize * 7) / 7f / 2f;
        refresh();
    }

    // region 对外方法
    public void setShowNumber(boolean showNumber) {
        isShowNumber = showNumber;
        refresh();
    }

    // 月类型的，只需要知道年月
    public void setDateInfo(int year, int month) {
        setDateInfo(false, year, month, 1);
    }

    // 周类型的，传入本周周一的day
    public void setDateInfo(int year, int month, int day) {
        setDateInfo(true, year, month, day);
    }

    // 传入第一天的年月日
    private void setDateInfo(boolean isWeek, int year, int month, int day) {
        this.isWeek = isWeek;
        mYear = year;
        mMonth = month;
        mDay = day;
        mLastDay = TimeUtils.getTotalDayOfMonth(year, month);
        mFirstDayWeek = TimeUtils.getDayOfWeekMonday(String.format(Locale.getDefault(),
                "%d-%02d-%02d", year, month, day));
        refresh();
    }

    public void setData(List<StatisticsBean> statisticsBeanList) {
        mStatisticsBeanList = statisticsBeanList;
        refresh();
    }
    // endregion

    private void refresh() {
        if (CollectionUtils.isNotEmpty(mStatisticsBeanList) && mYear > 0 && mWidth > 0) {
            if (!isWeek && mStatisticsBeanList.size() != mLastDay) {
                // 按月，但长度不完整，则需要进行补齐
                StatisticsBean bean;
                for (int i = mDay; i <= mLastDay; i++) {
                    boolean hadFound = false;
                    for (StatisticsBean statisticsBean : mStatisticsBeanList) {
                        if (statisticsBean.getDay() == i) {
                            hadFound = true;
                            break;
                        }
                    }
                    if (!hadFound) {
                        bean = new StatisticsBean();
                        bean.status = 2;
                        bean.date = String.format(Locale.getDefault(),
                                "%d-%02d-%02d", mYear, mMonth, i);
                        mStatisticsBeanList.add(bean);
                    }
                }
            }

            int line;
            if (isWeek) {
                line = 1;
            } else {
                int total = mFirstDayWeek - mDay + mLastDay;
                if (total % 7 == 0)
                    line = total / 7;
                else
                    line = total / 7 + 1;
            }
            mVerticalSpace = line == 1 ? mHeight - mItemSize : ((mHeight - mItemSize * line) / (float) (line - 1));

            Rect rect;
            int day;
            for (StatisticsBean statisticsBean : mStatisticsBeanList) {
                rect = new Rect();
                day = statisticsBean.getDay();
                if (isWeek) {
                    rect.top = 0;
                    if (day < mDay) {
                        rect.left = (int) ((mLastDay - mDay + day) * (mItemSize + mItemPadding * 2) + mItemPadding);
                    } else {
                        rect.left = (int) ((day - mDay) * (mItemSize + mItemPadding * 2) + mItemPadding);
                    }
                } else {
                    int actTotalDay = day + mFirstDayWeek - 1;
                    int curLine = actTotalDay / 7 + (actTotalDay % 7 == 0 ? 0 : 1);
                    rect.top = (int) ((curLine - 1) * (mItemSize + mVerticalSpace));
                    int dayOfWeek = (mFirstDayWeek + day - 1) % 7;
                    if (dayOfWeek == 0)
                        dayOfWeek = 7;
                    rect.left = (int) ((dayOfWeek - 1) * (mItemSize + mItemPadding * 2) + mItemPadding);
                }
                rect.bottom = rect.top + mItemSize;
                rect.right = rect.left + mItemSize;
                statisticsBean.rect = rect;
            }

            invalidate();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (CollectionUtils.isNotEmpty(mStatisticsBeanList)) {
            Drawable drawable;
            for (StatisticsBean statisticsBean : mStatisticsBeanList) {
                drawable = null;
                switch (statisticsBean.status) {
                    case -1:
                        drawable = mErrorDrawable;
                        break;
                    case 0:
                        drawable = mNormalDrawable;
                        break;
                    case 1:
                        drawable = mCorrectDrawable;
                        break;
                }
                if (drawable != null) {
                    drawable.setBounds(statisticsBean.rect);
                    drawable.draw(canvas);
                }

                if (isShowNumber && statisticsBean.needDrawDay()) {
                    canvas.drawText(String.valueOf(statisticsBean.getDay()),
                            (statisticsBean.rect.left + statisticsBean.rect.right) / 2f,
                            (statisticsBean.rect.top + statisticsBean.rect.bottom) / 2f
                                    + Math.abs(mPaint.ascent() + mPaint.descent()) / 2f,
                            mPaint);
                }
            }
        }
    }
}
